我們都知道 Core Web Vitals 的指標包含 LCP、INP、CLS,也經常探討如何提升這些指標的表現,但我們很少有機會去了解這些指標的閾值定義,而這些指標的閾值定義是基於研究室的研究數據,但實際上我們的網站效能可能會因為不同的網路環境、不同的裝置而有不同的表現,因此本篇文章將會介紹各指標的閾值定義,並且會提供一些實際的數據來說明這些閾值定義是否合理。
在此之前,先回顧一下指標門檻的定義:至少 10% 的網站需達到「良好」標準,而表現最差的 10-30% 則被歸類為「不良」。
Largest Contentful Paint(LCP) 用於衡量頁面加載的速度,標記頁面最主要內容完成加載的時間點。與傳統指標(如 load 或 DOMContentLoaded)不同,LCP 更準確地反映使用者在螢幕上實際看到的內容。
LCP 基於 Largest Contentful Paint API,當頁面首次繪製時,瀏覽器會生成一個 PerformanceEntry 事件,類型為 largest-contentful-paint,來標記當時頁面上最大的內容元素。如果後續渲染中出現更大的元素,瀏覽器會再次生成新的 PerformanceEntry 事件,更新 LCP 的時間點。例如:
<p>
或 <h1>
)。我們需要知道 LCP 的閾值評估會受到 FCP (First Contentful Paint)的影響,因為 LCP 通常發生在 FCP 之後。而 FCP 的「良好」門檻已經設定為 1 秒,再加上即時反應時間的定義是根據 Card 和 Miller 的研究:
根據上述的研究,再加上 FCP 已占據的時間,可以推論出 LCP 的「良好」門檻可以被設定在 1 到 3 秒之間。然而,根據實驗數據和對網站效能的分析,最終選擇 2.5 秒 作為一致可達的「良好」門檻。細節的實驗會列出各種裝置所收集的數據進行分析,分析如下:
可以發現,能達到 1 秒閾值的網頁只有不到 10 %,但 1.5 秒到 3 秒之間的所有其他閾值仍然是有效的候選。在對表現最佳的網站進行分析後,我們發現 1.5 秒和 2 秒的閾值並不一致可達,而 2.5 秒的閾值則是一致可達的。因此將 LCP 的閾值定義為 2.5 秒,這不僅符合實驗結果,也符合實際使用者的體驗。
如果設定 4 秒作為閾值,約有 26% 的手機網站和 21% 的桌面網站會被歸類為「不良」。這符合 10-30% 的目標範圍,因此得出 4 秒是一個可接受的「不良」閾值。
INP(Interaction to Next Paint)是一個新的指標,從 2024 年 3 月起正式取代了 FID(First Input Delay)且 FID 也在 2024 年 9 月 11 日被淘汰。INP 考慮了整個頁面生命週期內的所有互動,而不僅僅是頁面載入後的第一次互動,因此能更準確地反映使用者體驗。
INP 會評估每次觸控、點擊或鍵盤與網頁互動時的延遲時間,並根據互動次數選取網頁互動延遲時間最低(或接近最高)的一個代表值,來表示網頁的整體回應速度。而這個延遲時間不會計算到整個互動的最終結果(例如伺服器回應或網絡請求的時間),而是注重從互動開始到瀏覽器進行下一次繪製的過程。例如下面動畫中點擊一個項目後,測量從點擊到顯示展開內容這種變化的時間。
然而關於『互動』和『互動次數』在 Web Vitals 中也有明確的定義:
在 Chrome 的分析中,使用者在頁面載入後有 90% 的時間都在與頁面互動,而在網頁上所謂的互動是進行例如點擊、觸控或鍵盤輸入等操作,這些操作會觸發一系列的 event handler
(如 pointerup
、mouseup
和 click
),然而在操作到處發 event 的期間也會有延遲,這段時間也會被記錄,event 觸發後再啟動渲染和繪製工作,最後再繪製下一幀,即是一個完整的互動過程。
🔥 TIP
因此由上圖可以推出,以下三種情況都會影響 INP 的表現:
- 輸入延遲:從使用者與網頁互動時,直到互動 event 開始執行的時間。
- event 處理時間長度:包含 event 回調函數所需的執行時間。
- 顯示延遲,瀏覽器顯示下一個幀所需的時間,包含互動的視覺結果。
然而網頁上的互動有非常多種,但會被 INP 紀錄的只有以下三種:
另外要特別注意的是,有些互動可能會發生在 iframe 中,例如影片撥放的點擊,但 JavaScript Web API 無法訪問 iframe 的內容,所以可能導致 CrUX 和 RUM 數據之間的差異。
對於具有大量互動的頁面,偶然的問題可能會導致頁面上出現一個不正常的高延遲互動。互動次數越多,發生這種情況的機率越高。
所以為了更準確地測量這些頁面的實際響應性,每發生 50 次互動,就會忽略一個延遲最長的互動。大多數頁面不會有超過 50 次互動,因此通常 INP 所記錄的是最差的互動。
而頁面本身的測量會從所有瀏覽中的第 75 百分位數,排除離群值後提供大多數使用者的實際體驗值或更好的數據。
🔥關於憤怒點擊使互動增加
在 Chrome 的分析中發現,網頁回應速度緩慢會使點擊發生率上升,這種行為就稱為憤怒點擊,特別是在 CLS 和 INP 指標較不良的情況下容易發生。然而如果點擊過多,反而會再進一步拖慢回應速度,導致惡性循環。
https://docs.google.com/presentation/d/1Euu4FBL75z0I8UtKf3dTzrLYu6wxfeWnrmXUCn9AQIY/edit?usp=sharing&resourcekey=0-t6sEnmSbzYTO_fcrR8n9Jg
雖然官方並沒有正式提供 INP 的閾值定義在 200ms 和 500ms 的原因,但可以從 FID 指標推論,例如下圖中 FID 的時間範圍是輸入延遲的期間,也就是紅色框起來的區域,而 FID 的閾值已經是 100ms, 300ms 所以合理推論再加上事件處理的時間與回應的延遲時間使得閾值為 200ms 和 500ms。
而 FID 的研究中也以 Michotte 的因果關係和 Miller 的控制觸發的回應為依據:
Cumulative Layout Shift (CLS) 是所謂的累計版面配置位移,這個指標主要是注重於視覺化內容穩定性,如果是非預期的版面配置位移可能會以多種方式乾擾使用者體驗,例如下方一個非常焦躁地動圖,使用者在閱讀文字時如果內容突然移動,導致點選錯誤的連結或按鈕,導致閱讀中斷或其他的行為,甚至會造成嚴重傷害。
CLS 是由 Layout Instability API 定義的,當頁面上的可見元素在兩個畫面更新之間發生位移時,這些元素被稱為不穩定元素。與其他指標不同,CLS 的閾值沒有單位,因為它是根據計算出的 layout shift score 來衡量的。
瀏覽器在計算 layout shift score 時,會檢查可見元素在兩個畫面更新之間的位置變化,並根據以下兩個因素計算得出:
影響分數(Impact Fraction):表示移動的元素在視窗中佔用了多少區域。假設一個元素在頁面中佔了一半的區域,那影響分數就是 0.5。如果元素移動後佔據更大或更小的區域,會影響這個分數。例如下圖中位移後佔比分數大增:
距離分數(Distance Fraction):代表元素移動的距離有多遠,與視窗的寬或高相比。如果一個元素移動了視窗高度的四分之一,距離分數就是 0.25。例如下圖藍色箭頭的位移距離:
layout shift score = Impact Fraction * Distance Fraction
假設有一個元素移動後佔據了 75% 的視窗面積(影響分數是 0.75),並且它移動了 25% 的視窗高度(距離分數是 0.25)。因此,Layout Shift Score = 0.75 * 0.25 = 0.1875。
hadRecentInput
,在計算時被排除。transform: scale()
和 transform: translate()
。在 Chrome 的內部測試中,發現 CLS 超過 0.15 會被使用者認為具有干擾性,而 0.1 以下的變動則不會造成明顯干擾。因此,0.1 被加入「良好」的 CLS 候選閾值。
後來根據 CrUX 資料,接近 50% 的網站 CLS 分數在 0.05 以下,這是一個可行的目標。但由於某些情況下(如嵌入第三方內容)難以避免較大的布局變動,所以最後 0.1 被認為是在「體驗品質」與「可達性」之間的平衡點。
而不良標準的分析中,大約有 20% 的網站達到 CLS 分數為 0.25,也符合目標範圍的 10-30%。
這個問題我想應該先從當初 Google 為什麼選擇使用 FID?當初 Google 認為 FID 是使用者在頁面載入後第一次與網頁互動到 event handler 可以執行的時間。這是當時他們認為可以非常實際地評估使用者體驗的方法。
後來也一直持續改進及開發一個新指標來擴展 FID 可以測量的範圍,並希望這個新指標可以符合以下幾點來反應更真實的使用者體驗:
而從下圖的比較中可以看出 FID 和 INP 的比較,確實 INP 更完整地呈現使用者在與網頁互動後,頁面所進行的歷程,也因為 FID 有這兩個限制,所以最後被 INP 取代:
我們一般在開發時多半會使用 Lighthouse 或是 Page Speed Insight (PSI) 作為網頁 Core Web Vitals 的測量,雖然 PSI 會參考 CrUX 和實驗室的資料,但從上一篇文章我們可以知道,如果實際使用者樣本數不足,最後還是使用實驗室的資料,因此造成我們在開發時會因為測量的方法都是實驗室數據,無法找出真正的指標問題點。
以 CLS 為例子,在 Lighthouse 中的數據永遠是【良好】,但等到 Search Console 每次取得 28 天的數據時,會一直呈現【不良】的狀態,這就是因為實驗室資料與實際資料不同,而原因可以為以下幾點:
https://web.dev/articles/inp
https://web.dev/blog/better-responsiveness-metric?hl=zh-tw
https://www.explainthis.io/zh-hant/swe/inp
https://vercel.com/blog/first-input-delay-vs-interaction-to-next-paint
https://web.dev/articles/optimize-cls?hl=zh-tw#lab-field